
#include "threadpool.h"
#include "password.h"
#include "syslog.h"
int WriteOrRead = 0; // 0读，1写
int exitpipe[2];

//********************************************************************************
//信号处理函数，通知子进程退出
//********************************************************************************
void sigfunc(int num)
{
	printf("sig %d is coming\n", num);
	//通过管道通知父进程退出
	char ch = 1;
	write(exitpipe[1], &ch, 1);
}

//********************************************************************************
//主函数
//********************************************************************************
int main(int argc, char *argv[])
{
	// ./server ip,port,processNum

	ARGS_CHECK(argc, 4);
	int threadNum = atoi(argv[3]);
	pipe(exitpipe); //创建退出的管道

	pid_t pid = fork();
	if (pid > 0)
	{
		signal(SIGUSR1, sigfunc); // 10号信号
		close(exitpipe[0]);
		wait(NULL);
		exit(0);
	}
	//子进程
	int epfd = epoll_create1(0);
	ERROR_CHECK(epfd, -1, "epoll_create1");

	//创建传输文件队列
	pfileQue fileque = (pfileQue)malloc(MAXCONNS * sizeof(fileQue));
	InitFileque(fileque);

	close(exitpipe[1]);
	thread_pool_t threadpool;
	threadpoolInit(&threadpool, threadNum, epfd);
	threadpoolStart(&threadpool);

	// 2. 创建TCP的监听套接字listenfd
	int listenfd = tcpInit(argv[1], atoi(argv[2]));

	// 3. 创建epoll的实例, 并注册(监听)相应文件描述符上的事件

	epollAddReadEvent(epfd, listenfd);
	epollAddReadEvent(epfd, exitpipe[0]);

	struct epoll_event *pevtList = (struct epoll_event *)
		calloc(MAXCONNS, sizeof(struct epoll_event));

	int nready;
	while (1)
	{
		do
		{
			// 4. epoll等待事件就绪
			nready = epoll_wait(epfd, pevtList, MAXCONNS, -1);
		} while (-1 == nready && errno == EINTR);

		if (0 == nready)
		{
			printf(">> epoll timeout.\n");
			continue;
		}
		else if (-1 == nready)
		{
			perror("epoll_wait");
			return EXIT_FAILURE;
		}
		else
		{ // nready > 0

			for (int i = 0; i < nready; ++i)
			{
				int fd = pevtList[i].data.fd;
				if (fd == listenfd)
				{ // 5. 客户端到来的处理
					int peerfd = accept(listenfd, NULL, NULL);
					if (peerfd < 0)
					{
						perror("accept");
					}
					printf("accept a new conn, peerfd: %d\n", peerfd);
					SendSysLog(getpid(), "accept a new conn");

					//监听新连接
					epollAddReadEvent(epfd, peerfd);
					AddfilequeNode(&threadpool.fileque,peerfd);
					printf("初始化新连接文件传输结点完成\n");
				}
				else if (fd == exitpipe[0])
				{
					//退出信号
					char exitflag;
					read(exitpipe[0], &exitflag, 1);
					printf("parent process ready to exit.\n");
					//收到退出的通知之后，子线程要逐步退出
					queueWakeup(&threadpool.queue);
					for (int j = 0; j < threadNum; ++j)
					{
						pthread_join(threadpool.threads[j], NULL);
					}
					printf("parent process pool exit\n");
					threadpoolDestroy(&threadpool);
					exit(0);
				}
				else
				{ //旧连接的信号
					printf("connect a new CMD\n");
					printf("peerfd = %d\n", fd);
					//取指令

					task_t *ptask = recvCmd(fd);
					//判断是否是登录注册
					if (ptask->type == CMD_TYPE_LOGIN || ptask->type == CMD_TYPE_REG)
						epollDelEvent(threadpool.epfd, ptask->peerfd);

					//找到本条指令的userid
					ptask->usrid = hashmap_get_int(threadpool.userPeerfdHash,fd);
					printf("cmd userid = %d\n",ptask->usrid);
					//指令加入任务队列
					taskEnqueue(&threadpool.queue, ptask);
				}
			}
		}
	}

	free(pevtList);
	close(listenfd);
	close(epfd);
	return 0;
}
